package authmiddleware

import (
	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/golang-jwt/jwt/v5"
	"time"
)

type JWTClaims struct {
	Qid  string `json:"qid"`
	Name string `json:"qname"`
	jwt.RegisteredClaims
}

// TODO: 加上fresh token和running token, 并且从配置文件读取Token有效时间和密钥;
const (
	JWTsecret    = "JJJJJ;CMJJ"
	JWTAliveTime = 24 * time.Hour
)

type LoginData struct {
	Name string `orm:"Name"`
	Qid  string `orm:"Qid"`
}

// 生成Token
func GenerateToken(loginData *LoginData) (string, error) {
	claims := &JWTClaims{
		Name: loginData.Name,
		Qid:  loginData.Qid,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(JWTAliveTime)),
			IssuedAt:  jwt.NewNumericDate(time.Now()),
			NotBefore: jwt.NewNumericDate(time.Now()),
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	signedToken, err := token.SignedString([]byte(JWTsecret))
	if err != nil {
		return "", gerror.NewCode(gcode.CodeInternalError, err.Error())
	}

	return signedToken, nil
}

func Auther(r *ghttp.Request) {
	tokenString := r.Header.Get("Authorization")
	if tokenString == "" {
		r.SetError(gerror.NewCode(gcode.CodeNotAuthorized, "未提供Token"))
		return
	}

	if len(tokenString) > 7 && tokenString[:7] == "Bearer " {
		tokenString = tokenString[7:]
	}

	claims := &JWTClaims{}
	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
		return []byte(JWTsecret), nil
	})

	if err != nil || !token.Valid {
		r.SetError(gerror.NewCode(gcode.CodeNotAuthorized, "Token无效或者已经过期"))
		return
	}

	r.SetCtxVar("username", claims.Name)
	r.SetCtxVar("qid", claims.Qid)
	r.Middleware.Next()
}
